package com.qzboot.basic.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.qzboot.basic.service.mapper.SysUserMapper;
import com.qzboot.common.constant.SysConst;
import com.qzboot.common.util.PasswordUtil;
import com.qzboot.facade.entity.SysRole;
import com.qzboot.facade.entity.SysUser;
import com.qzboot.facade.service.SysRoleService;
import com.qzboot.facade.service.SysUserRoleService;
import com.qzboot.facade.service.SysUserService;
import com.qzboot.facade.service.SysUserTokenService;
import com.qzboot.facade.support.CrudServiceImpl;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zengzhihong
 */
@Service
public class SysUserServiceImpl extends CrudServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysUserTokenService sysUserTokenService;

    @Override
    public SysUser getByUsername(String username) {
        return baseMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, username));
    }

    @Override
    public SysUser save(SysUser entity) {
        SysUser exist = this.getByUsername(entity.getUsername());
        Assert.isNull(exist, "用户名已存在");
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        entity.setPassword(PasswordUtil.sha256(StrUtil.isBlank(entity.getNewPassword()) ? SysConst.SYS_DEFAULT_PASSWORD : entity.getPassword(), salt));
        entity.setSalt(salt);
        baseMapper.insert(entity);
        //检查角色
        checkRole(entity.getRoleIdList(), entity.getCreateByUserId());
        //保存用户角色
        sysUserRoleService.saveUserRole(entity.getId(), entity.getRoleIdList());
        return entity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateById(SysUser entity) {
        Assert.isFalse(SysConst.ADMIN_USER_ID.equals(entity.getId()), "系统内置管理员不能被修改");
        SysUser sysUser = this.getById(entity.getId());
        Assert.notNull(sysUser, "用户不存在");
        //判断是否有修改的权限 非管理 只能修改自己创建的用户
        Assert.isTrue(SysConst.ADMIN_USER_ID.equals(entity.getUpdateByUserId())
                || entity.getUpdateByUserId().equals(sysUser.getCreateByUserId()), "无权更新该用户");
        entity.setCreateByUserId(null);
        entity.setCreateByUsername(null);
        entity.setSalt(null);
        entity.setUsername(null);
        //检查角色
        checkRole(entity.getRoleIdList(), entity.getUpdateByUserId());
        //判断密码是否有更改
        if (StrUtil.isNotBlank(entity.getNewPassword())) {
            //sha256加密
            String salt = RandomStringUtils.randomAlphanumeric(20);
            entity.setPassword(PasswordUtil.sha256(entity.getPassword(), salt));
            entity.setSalt(salt);
        }
        //更新用户
        boolean updateUser = SqlHelper.retBool(baseMapper.updateById(entity));
        //保存用户角色
        boolean saveUserRole = sysUserRoleService.saveUserRole(entity.getId(), entity.getRoleIdList());
        return updateUser && saveUserRole;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeById(Long id, Long byId) {
        Assert.isFalse(SysConst.ADMIN_USER_ID.equals(id), "系统内置管理员不能删除");
        SysUser sysUser = this.getById(id);
        Assert.notNull(sysUser, "用户不存在");
        //判断删除权限
        Assert.isTrue(SysConst.ADMIN_USER_ID.equals(byId)
                || byId.equals(sysUser.getCreateByUserId()), "无权删除该用户");
        //删除用户角色
        sysUserRoleService.removeByUserId(id);
        //删除用户TOKEN
        sysUserTokenService.removeByUserId(id);
        //删除用户
        this.removeById(id);
        return true;
    }

    @Override
    public boolean changePassword(Long id, String password, String newPassword) {
        //校验密码
        SysUser sysUser = this.getById(id);
        Assert.notNull(sysUser, "用户不存在");
        Assert.isTrue(sysUser.getPassword().equals(PasswordUtil.sha256(password, sysUser.getSalt())), "原密码不正确");
        SysUser newUser = new SysUser();
        newUser.setId(id);
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        newUser.setPassword(PasswordUtil.sha256(newPassword, salt));
        newUser.setSalt(salt);
        return SqlHelper.retBool(baseMapper.updateById(newUser));
    }

    /**
     * 校验角色权限
     *
     * @param roleIdList
     * @param byId
     */
    private void checkRole(List<Long> roleIdList, Long byId) {
        if (CollectionUtil.isEmpty(roleIdList)) {
            return;
        }
        if (SysConst.ADMIN_USER_ID.equals(byId)) {
            return;
        }
        List<SysRole> sysRoleList = sysRoleService.listByCreateBy(byId);
        List<Long> sourceList = sysRoleList.stream().map(SysRole::getId).collect(Collectors.toList());
        Assert.isTrue(sourceList.containsAll(roleIdList), "所选角色无权分配");
    }
}
